<?php
class Users extends Controller {
	
	public function __construct()
  {
    parent::Controller();
  }

  public function index() {
  	if( Current_User::user() ) {
  		Current_User::user()->refreshRelated();
	  	$data['userdata'] = Current_User::user()->toArray();
	  	$this->flatRoles($data['userdata'], true);
	  	$data['userdata']['logged_in'] = true;
	  	$data['userdata']['roles'] = ROLE_AUTHENTICATED_USER;
	  	$data['userdata']['permissions'] = Current_User::user()->getPermissionsName();
	  	$data['userdata'] = json_encode($data['userdata']);
	  	// if the user logged in has admin rights the controller send him to the administration section
  		if( Current_User::hasAccessFor(PERM_ADMINISTER_DOCUMENTS) && Current_User::hasAccessFor(PERM_ADMINISTER_USERS)) {
  			$data['title'] = 'Aministraci&oacute;n de Documentos y Usuarios';
	      $this->load->view('appview_admin', $data);
  		}
  		// otherwise the user goes to the reader section with some extra rights
  		else {
  			$data['title'] = 'Navegaci&oacute;n de Documentos';
  			$this->load->view('appview_reader', $data);
  		}
  	}  
  	// no user is currently logged in, so the controller use the reader section as restricted as possible
  	else {
    	$data['title'] = 'Navegaci&oacute;n de Documentos';
    	$data['userdata']['roles'] = ROLE_ANONYMOUS_USER;
    	$data['userdata']['logged_in'] = false;
			$data['userdata'] = json_encode($data['userdata']);
    	$this->load->view('appview_reader', $data);
    }
  }
    
  public function login() {
  	if( Current_User::user() ) {
    	redirect('users/index');
    }
    else {
    	$data['title'] = 'Registro de usuario';
    	$data['userdata']['roles'] = ROLE_ANONYMOUS_USER;
    	$data['userdata'] = json_encode($data['userdata']);
      $this->load->view('user/login', $data);
    }
  }

  /**
   * This function take as parameter a post request and send as response a boolean value
   * depending whether or not the username exists in the user table.
   * @return boolean
   */
  public function isUniqueUsername() {
  	if ( Doctrine_Core::getTable('User')->findOneByUsername($_POST['username']) ) {
  		echo 0;
  	}
  	else {
  		echo 1;
  	}
  }
  
  public function isUniqueEmail() {
  	if ( Doctrine_Core::getTable('User')->findOneByEmail($_POST['email']) ) {
  		echo 0;
  	}
  	else {
  		echo 1;
  	}	
  }
  
  /**
   * 
   * @return unknown_type
   */
	public function isPasswordValid() {
		$user = Doctrine_Core::getTable('User')->findOneByUsername($_POST['username']);
		if( $user && $user->password == $_POST['password'] ) {
  		echo '{success:true}';
  	}
  	else {
  		echo '{success:false, msg:"Lo siento, usted ha entrado una contrase&ntilde;a incorrecta!"}';
  	}	
  }

  /**
   * function called from the client 
   * AJAX call from ExtJS
   * @return unknown_type
   */
 	public function logout() {
  	$this->session->sess_destroy();
    echo "{success:true}";
  }

  /**
   * Uses as remote callback to authenticate the user.
   * AJAX call from ExtJS
   * @return unknown_type
   */
	public function authenticate() {
    if ( Current_User::authenticate($this->input->post('username', TRUE), $this->input->post('password', TRUE)) ) {
    	echo "{success:true}";	
    }
    else {
    	echo "{success:false, errors: { reason: 'Nombre de usuario o contraseña incorrecto!' }}";	
    }
  }
  
    /**
     * 
     * @return unknown_type
     */
    public function read() {
	    // collect request parameters
			$start  = isset($_REQUEST['start'])  ? $_REQUEST['start']  :  0;
			$count  = isset($_REQUEST['limit'])  ? $_REQUEST['limit']  : 20;
			$sort   = isset($_REQUEST['sort'])   ? $_REQUEST['sort']   : '';
			$dir    = isset($_REQUEST['dir'])    ? $_REQUEST['dir']    : 'ASC';
			$filters = isset($_REQUEST['filter']) ? $_REQUEST['filter'] : null;	
			
	  	// GridFilters sends filters as an Array if not json encoded
			if (is_array($filters)) {
			    $encoded = false;
			} else {
			    $encoded = true;
			    $filters = json_decode($filters);
			}
			
			// initialize variables
			$where = ' 0 = 0 ';
			$qs = '';
			
			// loop through filters sent by client
			if (is_array($filters)) {
			    for ($i=0;$i<count($filters);$i++){
			        $filter = $filters[$i];
			
			        // assign filter data (location depends if encoded or not)
			        if ($encoded) {
			            $field = $filter->field;
			            $value = $filter->value;
			            $compare = isset($filter->comparison) ? $filter->comparison : null;
			            $filterType = $filter->type;
			        } else {
			            $field = $filter['field'];
			            $value = $filter['data']['value'];
			            $compare = isset($filter['data']['comparison']) ? $filter['data']['comparison'] : null;
			            $filterType = $filter['data']['type'];
			        }
			
			        switch($filterType){
			            case 'string' : $qs .= " AND ".$field." LIKE '%".$value."%'"; Break;
			            case 'list' :
			                if (strstr($value,','))  {
			                    $fi = explode(',',$value);
			                    for ($q = 0; $q < count($fi); $q++){
			                        $fi[$q] = "'".$fi[$q]."'";
			                    }
			                    $value = implode(',',$fi);
			                    $qs .= " AND ".$field." IN (".$value.")";
			                } else {
			                    $qs .= " AND ".$field." = '".$value."'";
			                }
			            Break;
			            case 'boolean' : $qs .= " AND ".$field." = ".($value); Break;
			            case 'numeric' :
			                switch ($compare) {
			                    case 'eq' : $qs .= " AND ".$field." = ".$value; Break;
			                    case 'lt' : $qs .= " AND ".$field." < ".$value; Break;
			                    case 'gt' : $qs .= " AND ".$field." > ".$value; Break;
			                }
			            Break;
			            case 'date' :
			                switch ($compare) {
			                    case 'eq' : $qs .= " AND ".$field." = '".date('Y-m-d',strtotime($value))."'"; Break;
			                    case 'lt' : $qs .= " AND ".$field." < '".date('Y-m-d',strtotime($value))."'"; Break;
			                    case 'gt' : $qs .= " AND ".$field." > '".date('Y-m-d',strtotime($value))."'"; Break;
			                }
			            Break;
			        }
			    }
			    $where .= $qs;
			}
	
			$q = Doctrine_Query::create()
				->select('u.*, r.*')
				->from('User u')
				->leftJoin('u.roles r')
				->where($where);
				
	  	if ($sort != "") {
			    $q->orderBy($sort.' '.$dir);
			}
			
			$q->offset($start);
			$q->limit($count);
				
			$results = $q->execute(array(), Doctrine_Core::HYDRATE_ARRAY);
			$this->flatRoles($results);
			
			$q = Doctrine_Query::create()
				->select('COUNT(*) AS total')
				->from('User')
				->where($where);
			
			$result = $q->fetchArray();
			$total = $result[0]['total'];
	
			// return response to client
			echo json_encode(array('success' => true, 'message' => 'Datos cargardo exitosamente', 'users' => $total, 'data' => $results));
  }
  
  public function create() {
    $data = isset($_REQUEST['data']) ? json_decode($_REQUEST['data'], true) : 0;
  	
  	$sucessResult = true;
  	$message = '';
  	$result = null;
  	
  	if( $data ) {
  		try {
	  		$user = new User();
	  		if( isset($data['username']) ) {
					$user->username = $data['username'];
				}
				if( isset($data['encrytedPassword']) ) {
					$user->password = $data['encrytedPassword'];
				}
				if( isset($data['email']) ) {
					$user->email = $data['email'];
				}
				if( isset($data['status']) ) {
					$user->status = $data['status'] == 'on' ? 1 : 0;
				}
				if( !empty($data['roles']) ) {
		  		$dbroles = Doctrine_Core::getTable('Role')->findAll();
					$roles = explode(',', $data['roles']);
					foreach( $roles as $role) {
						$user->roles[] = $dbroles[((int)$role) - 1];
					}
				}
			
	    	$user->save();
	    	$result = $user->toArray();
	    	$this->flatRoles($result);
	    	$message = 'Usuario creado exitosamente.';
			} catch(Doctrine_Exception $e) {
				$sucessResult = false;	
  			$message = $e->getMessage();
  			$result = '';	
			}
  	}
  	else {
  		$sucessResult = false;	
  		$message = 'Datos no suministrados para la creaci&oacute;n.';
  	}

  	echo json_encode(array('success' => $sucessResult, 'message' => $message, 'data' => $result));
  }
  
  /**
   * 
   * @return unknown_type
   */
	public function update() {
		$data = isset($_REQUEST['data'])  ? json_decode($_REQUEST['data'], true) : 0;
  	
  	$sucessResult = true;
  	$message = '';
  	$result = null;
  	$error = '';

  	if( !$data ) {
  		$sucessResult = false;
  		$message = 'Error en los datos recibidos desde el cliente.';
  	}
  	else {
  		$user = new User();
  		$user->assignIdentifier($data['uid']);	// assign an Identifier to change from insert to update mode.
  		$user->refresh();												// refresh the record.
  		$user->refreshRelated();								// refresh the relationships.
  		
  		try {
  			$user->updateValues($data);
  			$user->save();
  			$result = $user->toArray();
  			$this->flatRoles($result);
  			$message = 'Usuario actualizado exitosamente.';
  		} catch(Doctrine_Exception $e) {
  			$error = $e->getMessage();
  			$sucessResult = false;
  			$message = 'Error en la actualizaci&oacute;n de los datos.';
  		}
  	}
  	
  	echo json_encode(array('success' => $sucessResult, 'message' => $message, 'data' => $result, 'error' => $error));
  }
  
	public function delete() {
  	$data = isset($_REQUEST['data'])  ? json_decode($_REQUEST['data']) : 0;
  	$success = false;
  	$message = '';
		$error = '';
		
  	if (!$data) {
  		$message = 'Error al eliminar record. Id(s) no proporcionado(s).';
  	}	else {
  		if (!is_array($data)) {
  		  $data = (int)$data;
  		  if ($data == 1 || $data == 2) {
  		    $message = 'El usuario con Id = '.$data.' es un usuario creado por el sistema y no se debe eliminar.';
  		    echo json_encode(array('success' => false, 'message' => $message, 'error' => 'Error al eliminar usuario'));  
  		    return;
  		  }
  		  
  			$user = Doctrine_Core::getTable('User')->find((int)$data);
  			if ($user !== false) {
	  			try {
	  				$user->UserRole->delete();
	  				$user->delete();
	  				$success = true;
	  				$message = 'Usuario eliminado exitosamente.';
			    } catch (Doctrine_Exception $e) {
			    	$success = false;
	  				$message = 'El usuario con Id = '.$data.' no pudo ser eliminado.';
	  				$error = $e->getMessage();
			    }
  			}
  		}
  		else {
	  		foreach($data as $user_id) {
	  			/*
	  			$q = Doctrine_Query::create()
		    		->delete('User')
		    		->addWhere('uid = ?', (int)$user_id);
		
		    	$deleted = $q->execute();
		    	
					if( !$deleted ) {
						$success = false;
	  				$message = 'El usuario con Id = '.$data.' no pudo ser eliminado.';
	  				echo '{"success":'.json_encode($success).', "message":"'.$message.'"}';
	  				return;
					}
					*/
	  		}
	  		$success = true;
	  		$message = 'Usuarios eliminados exitosamente.';
  		}
  	}
  	
  	echo json_encode(array('success' => $success, 'message' => $message, 'error' => $error));
  }

  /**
   * Convert result roles object into an scv
   * @param array $result
   * @return none
   */
  private function flatRoles(array &$result, $rolesName = false) {
  	// if result has more than one user then result has not the roles key in the root of the array
  	if( !isset($result['roles']) ) {
	  	for( $i = 0; $i < count($result); $i++ ) {
	  		if( isset($result[$i]['roles']) ) {
	  			$roles = $result[$i]['roles'];
	  			unset($result[$i]['roles']);
	  			
	  			$stringRoles = '';
	  			$separator = '';
			  	foreach ($roles as $role)	{
			  		$stringRoles .= $separator;
			  		$stringRoles = !$rolesName ? $stringRoles.$role['id'] : $stringRoles.$role['name'];
			  		$separator = ',';	
			  	}
			  	$result[$i]['roles'] = $stringRoles;
	  		}
	  	}
  	}
  	else { // check for a sigle result
  		if( isset($result['roles']) ) {
  			$roles = $result['roles'];
  			unset($result['roles']);
  			
  			$stringRoles = '';
  			$separator = '';
		  	foreach ($roles as $role)	{
		  		$stringRoles .= $separator;
		  		$stringRoles = !$rolesName ? $stringRoles.$role['id'] : $stringRoles.$role['name'];
		  		$separator = ',';	
		  	}
		  	$result['roles'] = $stringRoles;
  		}
  	}
  }
  
  public function getPermissions() {
  }

  public function getOnlineUsers() {
  	if( Current_User::user() && Current_User::hasAccessFor(PERM_ADMINISTER_USERS) ) {
  		// Count users active within the defined period.
    	$interval = time() - 900;	
    	$q = Doctrine_Query::create()
				->select('s.*')
				->from('Session s')
				->where('s.last_activity >= ?', $interval);
				
			$results = $q->execute(array(), Doctrine_Core::HYDRATE_ARRAY);
			$nodes = array();
			foreach($results as $session) {
				$CI =& get_instance();
				$data = $CI->session->_unserialize($session['user_data']);
				if( !empty($data) ) {
					$nodes[] = array(
						'text' => $data['username'],
						'id' => $data['user_id'],
						'leaf' => true,
						'qtip' => '<b>IP</b>: '.$session['ip_address'].'<br/><b>email</b>:'.$data['email'].'<br/><b>Agent</b>: '.$session['user_agent'],
						'iconCls' => 'silk-user',
					);	
				}
			}
			echo json_encode($nodes);
  	}	
  }
}
